package src.main.java.com.huawei.demo;

import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.exception.ClientRequestException;
import com.huaweicloud.sdk.core.http.HttpConfig;
import com.huaweicloud.sdk.core.utils.StringUtils;
import com.huaweicloud.sdk.iam.v3.IamClient;
import com.huaweicloud.sdk.iam.v3.model.AgencyAuth;
import com.huaweicloud.sdk.iam.v3.model.AgencyAuthIdentity;
import com.huaweicloud.sdk.iam.v3.model.AssumeroleSessionuser;
import com.huaweicloud.sdk.iam.v3.model.CreateTemporaryAccessKeyByAgencyRequest;
import com.huaweicloud.sdk.iam.v3.model.CreateTemporaryAccessKeyByAgencyRequestBody;
import com.huaweicloud.sdk.iam.v3.model.CreateTemporaryAccessKeyByAgencyResponse;
import com.huaweicloud.sdk.iam.v3.model.CreateTemporaryAccessKeyByTokenRequest;
import com.huaweicloud.sdk.iam.v3.model.CreateTemporaryAccessKeyByTokenRequestBody;
import com.huaweicloud.sdk.iam.v3.model.CreateTemporaryAccessKeyByTokenResponse;
import com.huaweicloud.sdk.iam.v3.model.IdentityAssumerole;
import com.huaweicloud.sdk.iam.v3.model.IdentityToken;
import com.huaweicloud.sdk.iam.v3.model.ServicePolicy;
import com.huaweicloud.sdk.iam.v3.model.ServiceStatement;
import com.huaweicloud.sdk.iam.v3.model.TokenAuth;
import com.huaweicloud.sdk.iam.v3.model.TokenAuthIdentity;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class Application {
    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        String ak = ""; // ak,必传
        String sk = ""; // sk,必传
        String domainId = ""; // 租户id:domainId,必传

        // 配置客户端属性
        HttpConfig config = HttpConfig.getDefaultHttpConfig();
        config.withIgnoreSSLVerification(true);

        // 创建认证
        GlobalCredentials auth = new GlobalCredentials()
            .withAk(ak)
            .withSk(sk)
            .withDomainId(domainId);

        // 创建请求客户端
        ArrayList<String> endpoints = new ArrayList<String>();
        endpoints.add(""); // 固定值，填入：https://iam.myhuaweicloud.com
        IamClient client = IamClient.newBuilder()
            .withCredential(auth)
            .withEndpoints(endpoints)
            .build();

        // 通过token获取临时访问密钥
        createTemporaryAccessKeyByToken(client);

        // 通过委托获取临时访问密钥
        createTemporaryAccessKeyByAgency(client);
    }

    private static void createTemporaryAccessKeyByToken(IamClient client) {
        int durationSeconds = 0; // AK、SK和securitytoken的有效期,时间单位为秒。取值范围:[900,86400] ,默认为15min。选填

        String version = ""; // 权限版本号。1.0:系统预置的角色。1.1创建自定义策略。必填
        // 授权项,指对资源的具体操作权限。格式为:服务名:资源类型:操作,例:vpc:ports:create。支持通配符号*,无需罗列全部授权项。必填
        ArrayList<String> actions = new ArrayList<String>();
        // actions里面需要添加授权项目，如下示例
        // actions.add("vpc:ports:create");
        String effect = ""; // 固定值，填Allow或者Deny。必填

        // 构造请求
        CreateTemporaryAccessKeyByTokenRequest request = new CreateTemporaryAccessKeyByTokenRequest();
        CreateTemporaryAccessKeyByTokenRequestBody body = new CreateTemporaryAccessKeyByTokenRequestBody();

        // 获取listPolicyStatement
        List<ServiceStatement> listPolicyStatement = getListPolicyStatement(actions, effect);

        ServicePolicy policyIdentity = new ServicePolicy();
        policyIdentity.withVersion(version)
            .withStatement(listPolicyStatement);
        IdentityToken tokenIdentity = new IdentityToken();
        if (durationSeconds >= 900 && durationSeconds <= 86400) {
            tokenIdentity.withDurationSeconds(durationSeconds);
        }

        List<TokenAuthIdentity.MethodsEnum> listIdentityMethods = new ArrayList<TokenAuthIdentity.MethodsEnum>();
        listIdentityMethods.add(TokenAuthIdentity.MethodsEnum.fromValue("token"));
        TokenAuthIdentity identityAuth = new TokenAuthIdentity();
        identityAuth.withMethods(listIdentityMethods)
            .withToken(tokenIdentity)
            .withPolicy(policyIdentity);
        TokenAuth authbody = new TokenAuth();
        authbody.withIdentity(identityAuth);
        body.withAuth(authbody);
        request.withBody(body);

        try {
            // 执行请求
            CreateTemporaryAccessKeyByTokenResponse response = client.createTemporaryAccessKeyByToken(request);
            logger.info(response.toString());
        } catch (ClientRequestException e) {
            LogError(e);
        }
    }

    private static void createTemporaryAccessKeyByAgency(IamClient client) {

        String version = "1.1"; // 权限版本号。1.0:系统预置的角色。1.1创建自定义策略。必填
        // 授权项,指对资源的具体操作权限。格式为:服务名:资源类型:操作,例:vpc:ports:create。支持通配符号*,无需罗列全部授权项。必填
        ArrayList<String> actions = new ArrayList<String>();
        // actions里面需要添加授权项目，如下示例
        // actions.add("vpc:ports:create");
        String effect = ""; // 固定值，填Allow或者Deny。必填
        String agencyName = ""; // 委托名。必填
        // domainId和domainName二选一
        String domainId = ""; // 委托方的账号ID。二选一
        String domainName = ""; // 委托方的账号名。二选一

        // 委托方对应的企业用户名长度5~64,只能包含大写字母、小写字母、数字(0-9)、特殊字符("-"与"_")且只能以字母开头。选填
        String sessionUserName = "";
        int durationSeconds = 0; // AK、SK和securitytoken的有效期,时间单位为秒。取值范围:[900,86400] ,默认为15min。选填

        // 构造请求
        CreateTemporaryAccessKeyByAgencyRequest request = new CreateTemporaryAccessKeyByAgencyRequest();
        CreateTemporaryAccessKeyByAgencyRequestBody body = new CreateTemporaryAccessKeyByAgencyRequestBody();

        // 获取listPolicyStatement
        List<ServiceStatement> listPolicyStatement = getListPolicyStatement(actions, effect);

        ServicePolicy policyIdentity = new ServicePolicy();
        policyIdentity.withVersion(version)
            .withStatement(listPolicyStatement);

        IdentityAssumerole assumeRoleIdentity = new IdentityAssumerole();
        assumeRoleIdentity.withAgencyName(agencyName);
        if (!StringUtils.isEmpty(domainId)) {
            assumeRoleIdentity.withDomainId(domainId);
        } else if (!StringUtils.isEmpty(domainName)) {
            assumeRoleIdentity.withDomainName(domainName);
        }
        if (durationSeconds >= 900 && durationSeconds <= 86400) {
            assumeRoleIdentity.withDurationSeconds(durationSeconds);
        }
        if (!StringUtils.isEmpty(sessionUserName)) {
            AssumeroleSessionuser sessionUserAssumeRole = new AssumeroleSessionuser();
            sessionUserAssumeRole.withName(sessionUserName);
            assumeRoleIdentity.withSessionUser(sessionUserAssumeRole);
        }

        List<AgencyAuthIdentity.MethodsEnum> listIdentityMethods = new ArrayList<AgencyAuthIdentity.MethodsEnum>();
        listIdentityMethods.add(AgencyAuthIdentity.MethodsEnum.fromValue("assume_role"));
        AgencyAuthIdentity identityAuth = new AgencyAuthIdentity();
        identityAuth.withMethods(listIdentityMethods)
            .withAssumeRole(assumeRoleIdentity)
            .withPolicy(policyIdentity);
        AgencyAuth authbody = new AgencyAuth();
        authbody.withIdentity(identityAuth);
        body.withAuth(authbody);
        request.withBody(body);

        try {
            // 执行请求
            CreateTemporaryAccessKeyByAgencyResponse response = client.createTemporaryAccessKeyByAgency(request);
            logger.info(response.toString());
        } catch (ClientRequestException e) {
            LogError(e);
        }
    }

    private static List<ServiceStatement> getListPolicyStatement(ArrayList<String> actions, String effect) {
        List<String> listStatementAction = new ArrayList<String>();
        for (String action : actions) {
            listStatementAction.add(action);
        }
        List<ServiceStatement> listPolicyStatement = new ArrayList<ServiceStatement>();
        listPolicyStatement.add(
            new ServiceStatement()
                .withAction(listStatementAction)
                .withEffect(ServiceStatement.EffectEnum.fromValue(effect))
        );
        return listPolicyStatement;
    }

    private static void LogError(ClientRequestException e) {
        logger.error("HttpStatusCode: " + e.getHttpStatusCode());
        logger.error("RequestId: " + e.getRequestId());
        logger.error("ErrorCode: " + e.getErrorCode());
        logger.error("ErrorMsg: " + e.getErrorMsg());
    }
}

